package com.lingxu.base.common.util;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECPoint;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.util.encoders.Hex;

import java.math.BigInteger;

public class Sm2Util {
    private static final String privateKey = "0087f007f8ea1a46f7da2b91de63eebeef15a691325281bef9c8b87892665fb021";
    private static final String publicKey = "046e6033c75558334a50e8fe767f6a5d52b3f84e3af01f4aaa92633d9c4f0ebb5616eab4f3cf483b60ff0a10e0f4022fef15b989a54acec0a95564995a8adb011f";

    public static String encrypt(String data) {
        byte[] plaintextByte = Base64.encodeBase64(data.getBytes());
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domainParams = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
        X9ECPoint localX9ECPoint = new X9ECPoint(sm2ECParameters.getCurve(), Hex.decode(publicKey.getBytes()));
        ECPublicKeyParameters pk = new ECPublicKeyParameters(localX9ECPoint.getPoint(), domainParams);
        CipherParameters pubKeyParameters = new ParametersWithRandom(pk);
        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(true, pubKeyParameters);
        try {
            return Hex.toHexString(sm2Engine.processBlock(plaintextByte, 0, plaintextByte.length));
        } catch (InvalidCipherTextException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 解密
     *
     * @param data
     * @return
     */
    public static String decrypt(String data) {
        byte[] cipherDataByte = Hex.decode(data);

        //刚才的私钥Hex，先还原私钥
        BigInteger privateKeyD = new BigInteger(privateKey, 16);
        X9ECParameters sm2ECParameters1 = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domainParameters1 = new ECDomainParameters(sm2ECParameters1.getCurve(), sm2ECParameters1.getG(), sm2ECParameters1.getN());
        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters1);

        //用私钥解密
        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(false, privateKeyParameters);

        //processBlock得到Base64格式，记得解码
        byte[] arrayOfBytes = new byte[0];
        try {
            arrayOfBytes = Base64.decodeBase64(sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length));
        } catch (InvalidCipherTextException e) {
            e.printStackTrace();
        }

        //得到明文：SM2 Encryption Test
        return new String(arrayOfBytes);
    }

    public static void main(String[] args) throws Exception {
        String password = "2020@lingxu";
        Sm2Util sm2Util = new Sm2Util();
        String jiami = sm2Util.encrypt(password);
        System.out.println(jiami);
        String jiemi = sm2Util.decrypt("0415619bd036be6bfba8fd0c3d6db200bc070810e9d6c0c9020f387ee70ed90495756d2cd6066fe21b7dcc2ad6e228e1a46e8591fdbfbc719881d2930e348402cab59f4c9a912023c08fe165e3079a11cf89df373633d588a018029b0638bf8899c51dc89b82e86a5a2c29020fb48b6ddd");
        System.out.println(jiemi);


        //X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        //ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
        //ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
        //keyPairGenerator.init(new ECKeyGenerationParameters(domainParameters, SecureRandom.getInstance("SHA1PRNG")));
        //AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();
        ////上面的代码都是直接用maven依赖中的包直接import就可以用了
        ////还有一些更底层的写法，可以自己搜索一下，图方便的这个挺好的
        ////私钥，16进制格式，自己保存
        //BigInteger privatekey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();
        //String privateKeyHex = privatekey.toString(16);
        //System.out.println("private Key :" + privateKeyHex);
        //
        ////公钥，16进制格式，发给前端
        //ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();
        //String publicKeyHex = Hex.toHexString(ecPoint.getEncoded(false));
        //System.out.println("Public Key :" + publicKeyHex);

        //System.out.println(Sm2Util.encrypt("测试"));
        //System.out.println(Sm2Util.decrypt("0466727b5e1483abdf462a67acbde6e530d2b814036c5fbdf6afac6767ca820c331623cb7d8cd223e932963a5b32360dff24aadd1da9325d28c6c8e6014cf6a2234faa665c08e4ace53c9cb4f915fa08c444a0ac8777754330e793c749aa9e8462da19ec9f39cd43758366766dc6b45cf8c9c1824507476405"));

        //// 加密
        //BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
        ////自己设置的秘钥
        //textEncryptor.setPassword("SXS");
        //String userName = textEncryptor.encrypt("jdbc:oscar://172.26.120.217:2003/osrdb");
        //System.out.println(userName);
        //// 解密
        //BasicTextEncryptor textEncryptor2 = new BasicTextEncryptor();
        //textEncryptor2.setPassword("SXS");
        //String oldPassword = textEncryptor2.decrypt("vBnk87EAr4FNghZn5wsfuZaNIZ8llFzA2fW17cBlzyhdQG7S8jU2GbWPF53sgZ1W");
        //System.out.println(oldPassword);
        //System.out.println("--------------------------");
    }
}
